/* ************************************************************************
 *       Filename:  test.c
 *    Description:  
 *        Version:  1.0
 *        Created:  2018年09月29日 11时23分59秒
 *       Revision:  none
 *       Compiler:  gcc
 *         Author:  YOUR NAME (), 
 *        Company:  
 * ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#include "link.h"
#include "tools.h"

#define BREAK_NUM 9999
#define BREAK_BUF "9999"
#define THREADMAX 10
// 链表处理ID
enum LINK_ID
{
	END_PROGREAM = 0x00,
	CREATE_LINK,
	SHOW_LINK,
	FREE_LINK,
	ORDER_LINK,
	REVERSE_LINK,
	DELETE_NODE_AS_COUNT,
	DELETE_BODE_AS_BUFFER,
	FIND_NODE_AS_COUNT,
	FIND_NODE_AS_BUFFER,
	INSERT_NODE_AS_COUNT,	
}LINK_ID;

// 线程ID
enum THREAD_ID
{
	INPUT_THREAD,
	OUTPUT_THREAD,
}THREAD_ID;

// 结构体
struct link_info
{
	s_msg_t *p_head;
	s_msg_t *new_nodes;

	pthread_t link_thread[THREADMAX];
	pthread_mutex_t linkmut;
}li_t;

// function list start
void create_links(s_msg_t **head);
void find_nodes_as_count(s_msg_t *head);
void find_nodes_as_buffer(s_msg_t *head);
void find_nodes_as_buffer(s_msg_t *head);
void delete_nodes_as_count(s_msg_t **head);
void delete_nodes_as_buffer(s_msg_t **head);
void insert_nodes_as_count(s_msg_t **head);
void show_info();
void link_workbench();
void thread_workbench();
void *link_input_thread();
void *link_output_thread();

// function list end


// 创建/添加节点
void create_links(s_msg_t **head)
{
	s_msg_t *p_new_node = NULL;

	int i = 0;
	int node_num = 0;
	char *c_str = NULL;
	LOGD("Please input node numbers: ");
	scanf("%d", &node_num);
	creat_srand();
	for(i = 0; i < node_num; i++)
	{
		p_new_node = (s_msg_t *)malloc(sizeof(s_msg_t));
		memset(p_new_node, 0x00, sizeof(s_msg_t));
		p_new_node->count = creat_rand(10, 0);
		c_str = creat_str();
		strncpy(p_new_node->str, c_str, strlen(c_str));
		create_link(head, p_new_node);
	}

}

// 创建/添加节点 供线程使用
void create_links_t(s_msg_t **head, int node_num)
{
	s_msg_t *p_new_node = NULL;

	int i = 0;

	char *c_str = NULL;
	creat_srand();
	for(i = 0; i < node_num; i++)
	{
		p_new_node = (s_msg_t *)malloc(sizeof(s_msg_t));
		memset(p_new_node, 0x00, sizeof(s_msg_t));
		p_new_node->count = creat_rand(10, 0);
		c_str = creat_str();
		strncpy(p_new_node->str, c_str, strlen(c_str));
		create_link(head, p_new_node);
	}

}

// 查找节点
void find_nodes_as_count(s_msg_t *head)
{
	while(1)
	{
		LOGD("Find nodes for Count: ");
		int fCount = 0;
		scanf("%d", &fCount);
		if(BREAK_NUM == fCount)
		{
			return ;
		}
		serach_node_for_link_as_count(head, fCount);
	}

}

// 查找节点
void find_nodes_as_buffer(s_msg_t *head)
{
	while(1)
	{
		LOGD("Find nodes for Buffer: ");
		char fBuffer[20] = {0};
		scanf("%s", fBuffer);
		if(0 == strcmp(fBuffer, BREAK_BUF))
		{
			return ;
		}
		serach_node_for_link_as_buffer(head, fBuffer);
	}
}

// 删除节点
void delete_nodes_as_count(s_msg_t **head)
{
	while(1)
	{
		LOGD("Delete nodes for Count: ");
		int dCount = 0;
		scanf("%d", &dCount);
		if(BREAK_NUM == dCount)
		{
			return ;
		}
		delete_nodes_for_link_as_count(head, dCount);
		show_link_nodes(*head);
	}
}

// 删除节点
void delete_nodes_as_buffer(s_msg_t **head)
{
	while(1)
	{
		LOGD("Delete nodes for Count: ");
		char dBuffer[20] = {0};
		scanf("%s", dBuffer);
		if(0 == strcmp(dBuffer, BREAK_BUF))
		{
			return ;
		}
		delete_nodes_for_link_as_buffer(head, dBuffer);
		show_link_nodes(*head);
	}
}

// 插入节点
void insert_nodes_as_count(s_msg_t **head)
{
	s_msg_t *p_new = NULL;
	while(1)
	{
		LOGD("Please input new nodes Count and Buffer: ");
		p_new = (s_msg_t *)malloc(sizeof(s_msg_t));
		memset(p_new, 0x00, sizeof(s_msg_t));
		scanf("%d %s", &(p_new->count), p_new->str);
		if((0 == strcmp(p_new->str, BREAK_BUF)) || (BREAK_NUM == p_new->count))
		{
			return ;
		}
		insert_nodes_for_link_as_count(head, p_new);
	}	
}

// 显示信息
void show_info()
{
	printf("*****************************************\n");
	printf("**  1.  Creat   link(Auto).            **\n");
	printf("**  2.  Print   link.                  **\n");
	printf("**  3.  Free    link.                  **\n");
	printf("**  4.  Order   link.                  **\n");
	printf("**  5.  Reverse Link.                  **\n");
	printf("**  6.  Delete  node as Count.         **\n");
	printf("**  7.  Delete  node as Buffer.        **\n");
	printf("**  8.  Find    node as Count.         **\n");
	printf("**  9.  Find    node as Buffer.        **\n");
	printf("** 10.  Insert  node as Count.         **\n");
	printf("**  0.  Exit Program.                  **\n");
	printf("*****************************************\n");
}

// 工作台
void link_workbench()
{
	s_msg_t *head = NULL;
	int info_id   = 0;
	while(1)
	{
		LOGD("Please Enter list number: ");
		scanf("%d", &info_id);
		switch(info_id)
		{
			case CREATE_LINK:
			{
				create_links(&head);
			}
			break;
			
			case SHOW_LINK:
			{
				LOGD("====== Show link nodes ======");
				show_link_nodes(head);
			}
			break;
			
			case FREE_LINK:
			{
				free_link(&head);
			}
			break;

			case ORDER_LINK:
			{
				order_link(&head);
			}
			break;

			case REVERSE_LINK:
			{
				reverse_link(&head);
			}
			break;
			
			case DELETE_NODE_AS_COUNT:
			{
				delete_nodes_as_count(&head);
			}
			break;
			
			case DELETE_BODE_AS_BUFFER:
			{
				delete_nodes_as_buffer(&head);
			}
			break;
			
			case FIND_NODE_AS_COUNT:
			{
				find_nodes_as_count(head);
			}
			break;
			
			case FIND_NODE_AS_BUFFER:
			{
				find_nodes_as_buffer(head);
			}
			break;

			case INSERT_NODE_AS_COUNT:
			{
				insert_nodes_as_count(&head);
			}
			break;
			
			case END_PROGREAM:
			{
				exit(0);
			}
			break;
			
			default:
			{
				LOGD("Please enter the correct data(0 ~ 6).");
			}
			break;
		}
		LOGD("====== Show link nodes ======");
		show_link_nodes(head);
		show_info();
	}
}

// Input Thread
void *link_input_thread()
{
	pthread_detach(pthread_self());	
	pthread_mutex_lock(&li_t.linkmut);
	
	LOGD("Input Thread.");
	//DELAY_S(5);
	create_links_t(&li_t.p_head, 10);
	
	pthread_mutex_unlock(&li_t.linkmut);	
	return NULL;
}

// Output Thread
void *link_output_thread()
{
	pthread_detach(pthread_self());
	pthread_mutex_lock(&li_t.linkmut);
	
	LOGD("Output Thread.");
	DELAY_S(2);
	show_link_nodes(li_t.p_head);
	
	pthread_mutex_unlock(&li_t.linkmut);	
	return NULL;
}


// 工作线程
void thread_workbench()
{
	LOGD("Thread workbench.");
	pthread_mutex_init(&li_t.linkmut, NULL);
	
	int errorCodeInput = pthread_create(&li_t.link_thread[INPUT_THREAD], NULL, link_input_thread, NULL);
	if(0 != errorCodeInput)
	{
		LOGE("Input thread create error, return!");
		return ;
	}

	int errorCodeOutput = pthread_create(&li_t.link_thread[OUTPUT_THREAD], NULL, link_output_thread, NULL);
	if(0 != errorCodeOutput)
	{
		LOGE("Output thread create error, return!");
		return ;
	}

	LOGD("Input and Output thread create secuess!");
	
}

// 主函数
int main(int argc, char *argv[])
{
#if 1
	show_info();	
	link_workbench();
#else
	thread_workbench();
	while(1)
	{
		DELAY_S(100 * 60);
	}
#endif
	return 0;
}


